// src/models/user.ts
import mongoose, { Document, Schema } from 'mongoose'
import bcrypt from 'bcrypt'
import dayjs from 'dayjs'
import { Counter } from './counter'

export interface IUser extends Document {
  id: number
  username: string
  password: string
  email: string
  phone_number: number | null
  created_at: string
  updated_at: string
  status: number // 0:禁用 1:启用
  role: string
  avatar: string
  last_login: number
  gender: number // 0:未知 1:男 2:女
  address: string
  country: string
  language: string
  preferences: string
  social: string
  comparePassword: (candidatePassword: string) => Promise<boolean>
}

const UserSchema: Schema = new Schema({
  id: {
    type: Number,
    unique: true,
    description: '用户id'
  },
  username: {
    type: String,
    required: true,
    unique: true,
    description: '用户名'
  },
  password: {
    type: String,
    required: true,
    description: '密码'
  },
  email: {
    type: String,
    required: false,
    trim: true,
    description: '邮箱'
  },
  phone_number: {
    type: Number,
    required: false,
    trim: true,
    default: null,
    description: '电话号码'
  },
  created_at: {
    type: String,
    required: false,
    trim: true,
    default: () => dayjs().format('YYYY-MM-DD HH:mm:ss'),
    description: '创建时间'
  },
  updated_at: {
    type: String,
    required: false,
    trim: true,
    default: () => dayjs().format('YYYY-MM-DD HH:mm:ss'),
    description: '最后更新时间'
  },
  status: {
    type: Number,
    required: false,
    trim: true,
    enum: [0, 1], // 0:禁用 1:启用
    default: 1,
    description: '账户状态'
  },
  role: {
    type: String,
    required: false,
    trim: true,
    default: '',
    description: '角色'
  },
  avatar: {
    type: String,
    required: false,
    trim: true,
    default: '',
    description: '用户头像'
  },
  last_login: {
    type: Number,
    required: false,
    trim: true,
    default: 0,
    description: '最后登录时间'
  },
  gender: {
    type: Number,
    required: false,
    trim: true,
    enum: [0, 1, 2], // 0:未知 1:男 2:女
    default: 0,
    description: '性别'
  },
  address: {
    type: String,
    required: false,
    trim: true,
    default: '',
    description: '地址'
  },
  country: {
    type: String,
    required: false,
    trim: true,
    default: '',
    description: '国家'
  },
  language: {
    type: String,
    required: false,
    trim: true,
    default: 'zh-CN',
    description: '语言'
  },
  preferences: {
    type: String,
    required: false,
    trim: true,
    default: '{}',
    description: '偏好'
  },
  social: {
    type: String,
    required: false,
    trim: true,
    default: '{}',
    description: '社交平台'
  }
})

// 密码加密中间件
UserSchema.pre<IUser>('save', async function (next) {
  // 只有当密码存在且被修改时才进行加密
  if (!this.isModified('password') || !this.password) return next()

  try {
    // 生成盐值并加密密码
    const salt = await bcrypt.genSalt(10)
    this.password = await bcrypt.hash(this.password, salt)
    next()
  } catch (error: any) {
    next(error)
  }
})

// 保存前处理
UserSchema.pre<IUser>('save', async function (next) {
  if (this.isNew) {
    try {
      const counter = await Counter.findByIdAndUpdate(
        { _id: 'user_id' },
        { $inc: { seq: 1 } },
        { new: true, upsert: true }
      )
      this.id = counter.seq
      next()
    } catch (error: any) {
      next(error)
    }
  } else {
    next()
  }
})

// 更新时更新时间戳
UserSchema.pre<IUser>('findOneAndUpdate', function (next) {
  // this.set({ updated_at: dayjs().format('YYYY-MM-DD HH:mm:ss') })
  next()
})

// 密码比较方法
UserSchema.methods.comparePassword = async function (
  candidatePassword: string
): Promise<boolean> {
  if (!this.password) return false
  return await bcrypt.compare(candidatePassword, this.password)
}

// 在返回用户信息时移除密码字段
UserSchema.set('toJSON', {
  transform: function (doc, ret) {
    const { _id, __v, password, ...rest } = ret
    return rest
  }
})

// 第三个参数是集合名称
export const User = mongoose.model<IUser>('user', UserSchema, 'user')
